package cn.silver.framework.mybatis.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.silver.framework.core.utils.ServletUtils;
import cn.silver.framework.core.validate.AddGroup;
import cn.silver.framework.core.validate.EditGroup;
import cn.silver.framework.core.validate.QueryGroup;
import cn.silver.framework.idempotent.annotation.RepeatSubmit;
import cn.silver.framework.log.annotation.Log;
import cn.silver.framework.log.enums.OperateEnums;
import cn.silver.framework.mybatis.bean.BaseBean;
import cn.silver.framework.mybatis.bean.PageModel;
import cn.silver.framework.mybatis.domain.BaseEntity;
import cn.silver.framework.mybatis.param.BaseParam;
import cn.silver.framework.mybatis.service.IBaseService;
import cn.silver.framework.openapi.model.Result;
import cn.silver.framework.openapi.model.ResultPage;
import cn.silver.framework.satoken.utils.LoginHelper;
import cn.silver.framework.web.controller.ApiController;
import io.swagger.v3.oas.annotations.Operation;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static cn.silver.framework.mybatis.constant.PageContant.*;

/**
 * @author zhouxiaobo
 */
@Data
@Slf4j
@EqualsAndHashCode(callSuper = true)
public abstract class BaseController<S extends IBaseService<T, P, V>, T extends BaseEntity, P extends BaseParam, V extends BaseBean>
        extends ApiController {

    protected static final List<String> WHITE_AUTHS = new ArrayList<>();
    protected S baseService;
    private String code = "";
    private String title = "通用数据接口";
    private String permission = "";

    /**
     * 查询分页列表
     *
     * @param param 查询条件
     * @return 查询结果
     */
    @GetMapping("/list")
    @Log(operate = OperateEnums.SEAR_PAGE)
    @Operation(summary = "分页列表查询", description = "分页获取数据")
    public ResultPage<V> page(@Validated(QueryGroup.class) @ModelAttribute P param) {
        this.checkPermission("list");
        PageModel page = this.getPageInfo();
        if (StringUtils.isBlank(page.getOrderByColumn())) {
            page.setOrderByColumn(param.getOrderColumn());
        }
        if (StringUtils.isBlank(page.getIsAsc())) {
            page.setIsAsc(param.getOrderType());
        }
        return this.baseService.selectPage(page, param);
    }

    /**
     * 查询数据总数
     *
     * @param param
     * @return
     */
    @GetMapping("/count")
    @Log(operate = OperateEnums.SEAR_COUNT)
    @Operation(summary = "统计数据", description = "根据查询条件查询符合条件的数据总数")
    public Result<Long> count(@Validated(QueryGroup.class) @ModelAttribute P param) {
        this.checkPermission("count");
        return Result.ok("查询成功", this.baseService.selectCount(param));
    }

    /**
     * 获取详细信息
     *
     * @return
     */
    @GetMapping(value = {"/{id}"})
    @Log(operate = OperateEnums.SEAR_VIEW)
    @Operation(summary = "精确查询", description = "根据id查询数据")
    public Result<V> getOne(@PathVariable(required = false, value = "id") String id, @ModelAttribute P param) {
        this.checkPermission("detail");
        V entity = null;
        if (StringUtils.isNotBlank(id)) {
            entity = this.baseService.selectById(id);
        } else {
            entity = baseService.selectOne(param);
        }
        return Result.ok("查询成功", entity);
    }

    /**
     * 新增数据
     */
    @PostMapping
    @RepeatSubmit
    @Log(operate = OperateEnums.ALTER_SAVE)
    @Operation(summary = "新增数据", description = "新增一条新数据")
    public Result<Void> add(@Validated(AddGroup.class) @RequestBody V model) {
        this.checkPermission("add");
        baseService.insert(model);
        return Result.ok("保存成功");
    }

    /**
     * 修改客户信息
     */
    @RepeatSubmit
    @PutMapping()
    @Operation(summary = "修改数据", description = "根据Id修改一条数据")
    @Log(operate = OperateEnums.ALTER_UPDATE)
    public Result<Void> edit(@Validated(EditGroup.class) @RequestBody V model) {
        this.checkPermission("edit");
        baseService.update(model);
        return Result.ok("保存成功");
    }

    /**
     * 删除客户信息
     */
    @RepeatSubmit
    @DeleteMapping("/{ids}")
    @Log(operate = OperateEnums.ALTER_DELETE)
    @Operation(summary = "删除数据", description = "根据Id批量删除数据")
    public Result<Void> delete(@PathVariable String[] ids) {
        this.checkPermission("remove");
        this.baseService.deleteBatch(Arrays.asList(ids));
        return Result.ok("数据删除成功");
    }

    protected void checkPermission(String permission) {
        if (StringUtils.isBlank(this.permission) || WHITE_AUTHS.contains(this.permission)) {
            return;
        }
        if (LoginHelper.isSuperAdmin()) {
            return;
        }
        StpUtil.checkPermission(this.permission + ":" + permission);
    }

    protected PageModel getPageInfo() {
        PageModel model = new PageModel();
        model.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM));
        if (model.getPageNum() == null) {
            model.setPageNum(DEFAULT_PAGE_NUM);
        }
        model.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE));
        if (model.getPageSize() == null) {
            model.setPageSize(DEFAULT_PAGE_SIZE);
        }
        model.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
        model.setIsAsc(ServletUtils.getParameter(IS_ASC));
        model.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
        return model;
    }
}
